package com.teckteam.ptvsystem.controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.sql.Time;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JOptionPane;

import com.teckteam.ptvsystem.model.ScraperHelper;
import com.teckteam.ptvsystem.model.facade.PTVConstants;
import com.teckteam.ptvsystem.model.facade.PTVModel;
import com.teckteam.ptvsystem.model.facade.PTVSystem;
import com.teckteam.ptvsystem.view.LoadingDialog;
import com.teckteam.ptvsystem.view.PTVUserInterface;

/**
 * Listener class to handle Timetable update routine
 * 
 *
 */
public class UpdateTimetableListener implements ActionListener
{
   class TimetableUpdaterThread implements Runnable
   {  
      public void run()
      {
         PTVUserInterface frame = PTVUserInterface.getInstance();
         ScraperHelper scraper = new ScraperHelper(LoadingDialog.getInstance());
         ArrayList<LinkedHashMap<String, String[]>> result = new ArrayList<LinkedHashMap<String, String[]>>(); 
         // See PTVConstants.java for list of constants.
         
         try
         {
            // Trains
            for (int i = 0; i < PTVConstants.trainRouteID.length; i++)
            {
               LoadingDialog.getInstance().setProgress(i, String.format("Scraping timetable: %s", 
                     PTVConstants.trainRouteID[i]));
               result.add(scraper.getTimetableDetails(
                     PTVConstants.trainRouteID[i], PTVConstants.TIMETABLE_INBOUND,
                     PTVConstants.TIMETABLE_MONFRI, PTVConstants.TRAIN_FLAG));
               result.add(scraper.getTimetableDetails(
                     PTVConstants.trainRouteID[i], PTVConstants.TIMETABLE_INBOUND,
                     PTVConstants.TIMETABLE_SAT, PTVConstants.TRAIN_FLAG));
               
               result.add(scraper.getTimetableDetails(
                     PTVConstants.trainRouteID[i], PTVConstants.TIMETABLE_INBOUND,
                     PTVConstants.TIMETABLE_SUN, PTVConstants.TRAIN_FLAG));
               result.add(scraper.getTimetableDetails(
                     PTVConstants.trainRouteID[i],
                     PTVConstants.TIMETABLE_OUTBOUND,
                     PTVConstants.TIMETABLE_MONFRI, PTVConstants.TRAIN_FLAG));
               result.add(scraper.getTimetableDetails(
                     PTVConstants.trainRouteID[i],
                     PTVConstants.TIMETABLE_OUTBOUND, PTVConstants.TIMETABLE_SAT,
                     PTVConstants.TRAIN_FLAG));
               result.add(scraper.getTimetableDetails(
                     PTVConstants.trainRouteID[i],
                     PTVConstants.TIMETABLE_OUTBOUND, PTVConstants.TIMETABLE_SUN,
                     PTVConstants.TRAIN_FLAG));
            }   
            
            // Trams
            for (int i = 0; i < PTVConstants.tramRouteID.length; i++)
            {
               LoadingDialog.getInstance().setProgress(PTVConstants.trainRouteID.length + i,
                     String.format("Scraping timetable: %s", PTVConstants.tramRouteID[i]));
               
               if (PTVConstants.tramRouteID[i].compareTo("04834") != 0)
               { // Special case
                  result.add(scraper.getTimetableDetails(
                        PTVConstants.tramRouteID[i], PTVConstants.TIMETABLE_INBOUND,
                        PTVConstants.TIMETABLE_MONTHUR, PTVConstants.TRAM_FLAG));
                  result.add(scraper.getTimetableDetails(
                        PTVConstants.tramRouteID[i], PTVConstants.TIMETABLE_INBOUND,
                        PTVConstants.TIMETABLE_FRI, PTVConstants.TRAM_FLAG));
                  result.add(scraper.getTimetableDetails(
                        PTVConstants.tramRouteID[i], PTVConstants.TIMETABLE_INBOUND,
                        PTVConstants.TIMETABLE_SAT, PTVConstants.TRAM_FLAG));
                  result.add(scraper.getTimetableDetails(
                        PTVConstants.tramRouteID[i], PTVConstants.TIMETABLE_INBOUND,
                        PTVConstants.TIMETABLE_SUN, PTVConstants.TRAM_FLAG));
               }
               
               result.add(scraper.getTimetableDetails(
                     PTVConstants.tramRouteID[i], PTVConstants.TIMETABLE_OUTBOUND,
                     PTVConstants.TIMETABLE_MONTHUR, PTVConstants.TRAM_FLAG));
               result.add(scraper.getTimetableDetails(
                     PTVConstants.tramRouteID[i], PTVConstants.TIMETABLE_OUTBOUND,
                     PTVConstants.TIMETABLE_FRI, PTVConstants.TRAM_FLAG));
               result.add(scraper.getTimetableDetails(
                     PTVConstants.tramRouteID[i], PTVConstants.TIMETABLE_OUTBOUND,
                     PTVConstants.TIMETABLE_SAT,
                     PTVConstants.TRAM_FLAG));
               result.add(scraper.getTimetableDetails(
                     PTVConstants.tramRouteID[i], PTVConstants.TIMETABLE_OUTBOUND,
                     PTVConstants.TIMETABLE_SUN, PTVConstants.TRAM_FLAG));
            }
               
            // Buses
            for (int i = 0; i < PTVConstants.busRouteID.length; i++)
            {
               LoadingDialog.getInstance().setProgress(PTVConstants.trainRouteID.length
                     + PTVConstants.tramRouteID.length + i,
                     String.format("Scraping timetable: %s", PTVConstants.busRouteID[i]));
               if(PTVConstants.busRouteID[i].compareTo("08956") != 0
                     || PTVConstants.busRouteID[i].compareTo("0895E") != 0
                     || PTVConstants.busRouteID[i].compareTo("08961") != 0)
                  result.add(scraper.getTimetableDetails(
                        PTVConstants.busRouteID[i], PTVConstants.TIMETABLE_INBOUND,
                        PTVConstants.TIMETABLE_MONFRI, PTVConstants.BUS_FLAG));
               
               result.add(scraper.getTimetableDetails(
                     PTVConstants.busRouteID[i], PTVConstants.TIMETABLE_INBOUND,
                     PTVConstants.TIMETABLE_SAT, PTVConstants.BUS_FLAG));
               result.add(scraper.getTimetableDetails(
                     PTVConstants.busRouteID[i], PTVConstants.TIMETABLE_INBOUND,
                     PTVConstants.TIMETABLE_SUN, PTVConstants.BUS_FLAG));
               if(PTVConstants.busRouteID[i].compareTo("08956") != 0
                     || PTVConstants.busRouteID[i].compareTo("0895E") != 0
                     || PTVConstants.busRouteID[i].compareTo("08961") != 0)
                  result.add(scraper.getTimetableDetails(
                        PTVConstants.busRouteID[i], PTVConstants.TIMETABLE_OUTBOUND,
                        PTVConstants.TIMETABLE_MONFRI, PTVConstants.BUS_FLAG));
                  
               result.add(scraper.getTimetableDetails(
                     PTVConstants.busRouteID[i], PTVConstants.TIMETABLE_OUTBOUND,
                     PTVConstants.TIMETABLE_SAT, PTVConstants.BUS_FLAG));
            
               result.add(scraper.getTimetableDetails(
                     PTVConstants.busRouteID[i], PTVConstants.TIMETABLE_OUTBOUND,
                     PTVConstants.TIMETABLE_SUN, PTVConstants.BUS_FLAG));
            }
         } catch (ScrapeFailedException e)
         {
            //Handled
         } catch (PTVSiteSucksException e)
         {
            //Handled
         } finally
         {
            try 
            {
               PTVSystem.getInstance().refreshTimetable();
            } catch (FileNotFoundException e) 
            {
               //Don't care
            } finally
            {
               LoadingDialog.getInstance().setVisible(false);
               frame.refreshView();
               frame.setVisible(true);
            }
         }
      }
   }
   
   /**
    * Warn user in advance
    */
   public void actionPerformed(ActionEvent e)
   {
      int response = JOptionPane
            .showOptionDialog(
                  PTVUserInterface.getInstance(),
                  "The update process requires a working internet connection and may take a long time to complete.\n"
                        + "Are you sure you want to continue?",
                  "Empty database", JOptionPane.YES_NO_OPTION,
                  JOptionPane.QUESTION_MESSAGE, null, null, null);
      
      switch (response) {
         case JOptionPane.YES_OPTION:
            PTVUserInterface.getInstance().setVisible(false);
            updateTimetable();
            break;
      }
   }

   /**
    * Routine to launch update timetable using scraper Thread 
    */
   private void updateTimetable()
   {
      LoadingDialog.getInstance()
            .setLoading((PTVConstants.trainRouteID.length
                  + PTVConstants.tramRouteID.length + PTVConstants.busRouteID.length));
      
      Thread tut = new Thread(new TimetableUpdaterThread());
      tut.start();
   }
}
